package org.jsets.fastboot.frame.config;

import java.util.List;

import org.jsets.fastboot.frame.controller.ExceptionHandlerAdvice;
import org.jsets.fastboot.util.SpringContextHolder;
import org.jsets.fastboot.util.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

/**
 * 基础配置
 *
 * @author wangjie (https://github.com/wj596)
 * @date 2021.07.12 21:49
 * @since 0.1
 */
@Configuration
@EnableOpenApi
@EnableConfigurationProperties(value = {SwaggerProperties.class})
public class FrameAutoConfiguration implements ApplicationContextAware, EnvironmentAware {

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println("111111111111aaaaaaaaaa");
		SpringContextHolder.setApplicationContextIfNecessary(applicationContext);
	}

	@Override
	public void setEnvironment(Environment environment) {
		SpringContextHolder.setEnvironmentIfNecessary(environment);
	}
	
	@Bean
	public ExceptionHandlerAdvice exceptionHandlerAdvice() {
		return new ExceptionHandlerAdvice();
	}
	
	@Bean
	public Docket createRestApi(SwaggerProperties properties) {
		List<SecurityScheme> securitySchemes = Lists.newArrayList();
		securitySchemes.add(new ApiKey("Authorization", "Authorization", "header"));
		
		//文档描述信息
		ApiInfoBuilder apiInfoBuilder = new ApiInfoBuilder()
				.title(properties.getAppName() + " Api Doc")
				.description(properties.getAppDesc())
				.version("Application Version: " + properties.getAppVersion() + ", Spring Boot Version: " + SpringBootVersion.getVersion());
		
		if (StringUtils.notEmpty(properties.getContactName()) || StringUtils.notEmpty(properties.getContactUrl()) || StringUtils.notEmpty(properties.getContactEmail())) {
			apiInfoBuilder.contact(new Contact(properties.getContactName(), properties.getContactUrl(), properties.getContactEmail()));
		}
		ApiInfo apiInfo = apiInfoBuilder.build();
		
		//授权信息全局应用
		SecurityReference securityReference = new SecurityReference("Authorization", new AuthorizationScope[] { new AuthorizationScope("global", "") });
		SecurityContext securityContext = SecurityContext.builder().securityReferences(Lists.newArrayList(securityReference)).build();
		List<SecurityContext> securityContexts =  Lists.newArrayList(securityContext);
		
		System.out.println("2222222222222222aaaaaaaaaaa");
		return new Docket(DocumentationType.OAS_30).pathMapping("/")
				.enable(properties.getEnable())// 是否开启swagger，false为关闭
				.apiInfo(apiInfo) // 设置文档描述信息
				.host(properties.getAppDebugAddress())// 调试地址
				.select()// 选择哪些接口作为swagger的doc发布
				.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).paths(PathSelectors.any())
				.build().protocols(Sets.newHashSet("https", "http"))// 协议集合
				.securitySchemes(securitySchemes)// 授权信息设置，header token等认证信息
				.securityContexts(securityContexts);// 全局授权信息
	}

}